#pragma once
#include "COM_h.h"
#include "Define.h"
#include "ComGuid.h"
#include <tchar.h>

class CAnimals : public ISetName, public IDog, public ICat, public IPig
{
private:
    unsigned int m_nCnt;
    PTCHAR m_lpName;

public:
    CAnimals();
    ~CAnimals();

public:
    BEGIN_INTERFACE_TABLE()
        INTERFACE_TABLE_ENTRY(CAnimals, ISetName)
        INTERFACE_TABLE_ENTRY(CAnimals, IDog)
        INTERFACE_TABLE_ENTRY(CAnimals, ICat)
        INTERFACE_TABLE_ENTRY(CAnimals, IPig)
    END_INTERFACE_TABLE()

    DECLARE_DEFAULT_INTERFACE(CAnimals);

public:
    virtual HRESULT STDMETHODCALLTYPE SetName(IN LPOLESTR lpName);
    virtual HRESULT STDMETHODCALLTYPE Woof(IN const unsigned char* lpString);
    virtual HRESULT STDMETHODCALLTYPE Meow(IN const unsigned char* lpString);
    virtual HRESULT STDMETHODCALLTYPE Oink(IN const unsigned char* lpString);
};


class CAnimalsFactory : public IClassFactory
{
private:
    unsigned int m_nLockTick;

public:
    CAnimalsFactory();
    ~CAnimalsFactory();

public:
    inline unsigned int GetReferences() const { return m_nLockTick; }

public:

    //
    //  IUnknown
    //

    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();

    //
    //  IClassFactory
    //

    virtual HRESULT STDMETHODCALLTYPE CreateInstance(
        IN OPTIONAL IUnknown* pUnkOuter,
        IN REFIID riid,
        OUT void** ppvObject
    );
    virtual HRESULT STDMETHODCALLTYPE LockServer(IN BOOL fLock);
};


class CAnimalRoot : public IClassFactory, public IOleItemContainer
{
private:
    unsigned int m_nLockTick;

public:
    CAnimalRoot();
    ~CAnimalRoot();

public:
    BEGIN_INTERFACE_TABLE()
        INTERFACE_TABLE_ENTRY(CAnimalRoot, IClassFactory)
        INTERFACE_TABLE_ENTRY(CAnimalRoot, IOleItemContainer)
        INTERFACE_TABLE_ENTRY(CAnimalRoot, IParseDisplayName)
    END_INTERFACE_TABLE()

    DECLARE_NONEW_INTERFACE();

public:
    inline unsigned int GetReferences() const { return m_nLockTick; }

public:

    //
    //  IClassFactory
    //

    virtual HRESULT STDMETHODCALLTYPE CreateInstance(
        IN OPTIONAL IUnknown* pUnkOuter,
        IN REFIID riid,
        OUT void** ppvObject
    );
    virtual HRESULT STDMETHODCALLTYPE LockServer(IN BOOL fLock);

    //
    //  IParseDisplayName
    //

    virtual HRESULT STDMETHODCALLTYPE ParseDisplayName(
        IN IBindCtx* pbc,
        IN LPOLESTR pszDisplayName,
        OUT ULONG* pchEaten,
        OUT IMoniker** ppmkOut
    );

    //
    //  IOleContainer
    //

    virtual HRESULT STDMETHODCALLTYPE EnumObjects(
        IN DWORD grfFlags,
        OUT IEnumUnknown** ppenum
    );
    virtual HRESULT STDMETHODCALLTYPE LockContainer( IN BOOL fLock );

    //
    //  IOleItemContainer
    //

    virtual HRESULT STDMETHODCALLTYPE GetObject(
        IN LPOLESTR pszItem,
        IN DWORD dwSpeedNeeded,
        IN IBindCtx* pbc,
        IN REFIID riid,
        OUT void** ppvObject
    );
    virtual HRESULT STDMETHODCALLTYPE GetObjectStorage(
        IN LPOLESTR pszItem,
        IN IBindCtx* pbc,
        IN REFIID riid,
        OUT void** ppvStorage
    );
    virtual HRESULT STDMETHODCALLTYPE IsRunning(IN LPOLESTR pszItem);

};

EXTERN_C CAnimalRoot AnimalRoot;
EXTERN_C CAnimalsFactory AnimalsFactory;
